package xeroxware.framework.util;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.UUID;

/**
 * <pre>
 * CommonUtil
 * </pre>
 * 
 * @since 2012. 12. 24.
 * @author XEROXER
 */
public class CommonUtil {

	/**
	 * Null 여부를 리턴한다.
	 * 
	 * @param o
	 * @return
	 */
	public static boolean isNull(Object o) {
		boolean result = false;

		if (o == null) {
			result = true;
		} else {
			result = false;
		}

		return result;
	}

	/**
	 * Null이 아닌지 여부를 리턴한다.
	 * 
	 * @param o
	 * @return
	 */
	public static boolean isNotNull(Object o) {
		return !isNull(o);
	}

	/**
	 * Null 또는 공백 여부를 리턴한다.
	 * 
	 * @param o
	 * @return
	 */
	public static boolean isEmpty(Object o) {
		boolean result = false;

		if (o == null || "".equals((String) o)) {
			result = true;
		} else {
			result = false;
		}

		return result;
	}

	/**
	 * Null 또는 공백이 아닌지 여부를 리턴한다.
	 * 
	 * @param o
	 * @return
	 */
	public static boolean isNotEmpty(Object o) {
		return !isEmpty(o);
	}

	/**
	 * Null 또는 공백일 경우 Empty String을 리턴한다.
	 * 
	 * @param o
	 * @return
	 */
	public static String nullToString(Object o) {
		return nullToString(o, "");
	}

	/**
	 * Null 또는 공백일 경우 해당 String을 리턴한다.
	 * 
	 * @param o
	 * @param str
	 * @return
	 */
	public static String nullToString(Object o, String str) {
		String result = "";

		if (isEmpty(o)) {
			result = str;
		} else {
			result = (String) o;
		}

		if ("null".equals(result)) {
			result = str;
		}

		return result;
	}

	/**
	 * YYYYMMDD 형식의 현재 날짜 String을 반환한다.
	 * 
	 * @return
	 */
	public static String getDate() {
		Calendar cal = Calendar.getInstance();

		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DAY_OF_MONTH);

		String y = Integer.toString(year);
		String m = Integer.toString(month);
		String d = Integer.toString(day);

		if (month < 10)
			m = "0" + m;
		if (day < 10)
			d = "0" + d;

		return y + m + d;
	}

	/**
	 * YYYYMMDDHH24MISS 형식의 현재 날짜 및 시간 String을 반환한다.
	 * 
	 * @return
	 */
	public static String getDateTime() {
		Calendar cal = Calendar.getInstance();

		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DAY_OF_MONTH);
		int hour = cal.get(Calendar.HOUR_OF_DAY);
		int min = cal.get(Calendar.MINUTE);
		int sec = cal.get(Calendar.SECOND);

		String y = Integer.toString(year);
		String m = Integer.toString(month);
		String d = Integer.toString(day);
		String h = Integer.toString(hour);
		String mi = Integer.toString(min);
		String s = Integer.toString(sec);

		if (month < 10)
			m = "0" + m;
		if (day < 10)
			d = "0" + d;
		if (hour < 10)
			h = "0" + h;
		if (min < 10)
			mi = "0" + mi;
		if (sec < 10)
			s = "0" + s;

		return y + m + d + h + mi + s;
	}

	/**
	 * YYYYMM 형식의 현재 년월 String을 반환한다.
	 * 
	 * @return
	 */
	public static String getMonth() {
		Calendar cal = Calendar.getInstance();

		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;

		String y = Integer.toString(year);
		String m = Integer.toString(month);

		if (month < 10)
			m = "0" + m;

		return y + m;
	}

	/**
	 * delimiter로 구분된 년/월/일 String을 반환한다.
	 * 
	 * @param delimiter
	 * @return
	 */
	public static String getDatePath(String delimiter) {
		Calendar cal = Calendar.getInstance();

		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DAY_OF_MONTH);

		String y = Integer.toString(year);
		String m = Integer.toString(month);
		String d = Integer.toString(day);

		if (month < 10)
			m = "0" + m;
		if (day < 10)
			d = "0" + d;

		return y + delimiter + m + delimiter + d;
	}

	/**
	 * Unique한 랜덤 ID를 리턴한다. (36Byte)
	 * 
	 * @return
	 */
	public static String makeUUID() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 문자열 형식의 두개의 날짜의 일자 차이를 구한다.
	 * 
	 * @param start
	 *            시작일자
	 * @param end
	 *            종료일자
	 * @param format
	 *            DateFormat에서 사용되는 날짜 포맷
	 * @return 시작일자와 종료일자의 일수 차
	 * @throws Exception
	 *             ParseException(날짜형식 오류)
	 */
	public static long calcDateDiff(String start, String end, String format) throws Exception {
		SimpleDateFormat sm = new SimpleDateFormat(format);

		Calendar sta_cal = Calendar.getInstance();
		sta_cal.setTime(sm.parse(start));

		Calendar end_cal = Calendar.getInstance();
		end_cal.setTime(sm.parse(end));

		long diffMillis = end_cal.getTimeInMillis() - sta_cal.getTimeInMillis();

		return (diffMillis / (24 * 60 * 60 * 1000)) + 1;
	}

	/**
	 * 문자열 형식의 날짜 계산
	 * 
	 * @param date
	 *            문자열 형식의 날짜
	 * @param format
	 *            DateFormat에서 사용되는 날짜 포맷
	 * @param field
	 *            Calendar에서 사용되는 필드(예:Calendar.MONTH)
	 * @param amount
	 *            계산 수
	 * @return 계산된 문자열 날짜 형식
	 * @throws Exception
	 *             ParseException(날짜형식 오류)
	 */
	public static String addDate(String date, String format, int field, int amount) throws Exception {
		SimpleDateFormat sm = new SimpleDateFormat(format);
		Calendar cal = Calendar.getInstance();
		cal.setTime(sm.parse(date));
		cal.add(field, amount);
		return sm.format(cal.getTime());
	}

	/**
	 * 특정월의 마지막 일자를 구한다
	 * 
	 * @param date
	 *            문자열 형식의 날짜
	 * @param format
	 *            DateFormat에서 사용되는 날짜 포맷
	 * @return 마지막 일자
	 * @throws Exception
	 *             ParseException(날짜형식 오류)
	 */
	public static String getLastDay(String date, String format) throws Exception {
		SimpleDateFormat sm = new SimpleDateFormat(format);
		Calendar cal = Calendar.getInstance();
		cal.setTime(sm.parse(date));
		int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		return lastDay < 10 ? "0" + lastDay : String.valueOf(lastDay);
	}

	/**
	 * 해당 날짜에 실수 만큼 처리 ( 0.5 단위로 계산한다.
	 * 
	 * @param sEndDate
	 *            문자열 형식의 날짜
	 * @param nSumValue
	 *            BigDecimal값인 차이값
	 * @return 일자
	 * @throws Exception
	 *             ParseException(날짜형식 오류)
	 */
	public static String DataPeriodExtendDiff(String sEndDate, BigDecimal nSumValue) throws Exception {

		int sign = nSumValue.doubleValue() < 0 ? -1 : 1;
		int lSumValue = Math.abs(nSumValue.intValue()); // 정수
		double dSumValue = Math.abs(nSumValue.doubleValue()) - lSumValue; // 소수점
		if (dSumValue > 0.5) {
			dSumValue = ++lSumValue;
		} else if (dSumValue > 0) {
			dSumValue = lSumValue + 0.5;
		} else {
			dSumValue = lSumValue;
		}

		// 말일일 경우
		if ((sEndDate.substring(6, 8)).equals(CommonUtil.getLastDay(sEndDate, "yyyyMMdd"))) {
			sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.MONTH, sign * lSumValue);
			sEndDate = sEndDate.substring(0, 6) + CommonUtil.getLastDay(sEndDate, "yyyyMMdd");
			if (sign > 0) {
				if (dSumValue - lSumValue == 0.5) {
					sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.DAY_OF_MONTH, 15);
				}
			} else {
				if (dSumValue - lSumValue == 0.5) {
					sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.MONTH, -1);
					sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.DAY_OF_MONTH, 15);
					sEndDate = sEndDate.substring(0, 6) + "15";
				}
			}
			// 15일 경우
		} else {
			sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.MONTH, sign * lSumValue);
			if (sign > 0) {
				if (dSumValue - lSumValue == 0.5) {
					sEndDate = sEndDate.substring(0, 6) + CommonUtil.getLastDay(sEndDate, "yyyyMMdd");
				}
			} else {
				if (dSumValue - lSumValue == 0.5) {
					sEndDate = CommonUtil.addDate(sEndDate, "yyyyMMdd", Calendar.MONTH, -1);
					sEndDate = sEndDate.substring(0, 6) + CommonUtil.getLastDay(sEndDate, "yyyyMMdd");
				}
			}
		}

		return sEndDate;
	}
}